package com.dao.impl;


import com.dao.AddDao;
import com.entity.Book;
import com.entity.Operatebook;
import com.entity.Users;
import com.oracle.wls.shaded.org.apache.regexp.RE;
import com.util.DBUtil;
import org.jasypt.util.password.PasswordEncryptor;
import org.jasypt.util.password.StrongPasswordEncryptor;
import org.jasypt.util.text.StrongTextEncryptor;

import java.sql.*;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class AddDaoImpl implements AddDao {
    //添加
    public static final String ADD_USERS_SQL = "INSERT INTO users(username,pwdHash,pwhHashCode,birthday,sex,usertype,isfull,money) VALUES(?, ?, ?, ?, ?,?,?,?)";
    public static final String GET_BY_USERNAME = "SELECT userid, username, pwdHash,pwhHashCode, birthday,sex,usertype,isfull,money FROM users WHERE username=?";
    private static final String ADD_BOOK_SQL = "INSERT INTO book(bookname,author,publish,bookcount,booktype) VALUES (?,?,?,?,?)";
    private static final String GET_BY_BOOKNAME_SQL = "SELECT bookid,bookname,author,publish,bookcount,booktype FROM book WHERE bookname=? ";
    private static final String GET_BY_BOOKID_SQL = "SELECT bookid,bookname,publish,author,bookcount,booktype FROM book WHERE bookid=?";

    //修改密码
    //根据id查找更新
    private static final String GET_BY_USERID_SQL = "SELECT userid, username, pwdHash,pwhHashCode,birthday,sex,usertype,isfull,money FROM users WHERE userid=?";
    private static final String GET_BY_USERNAME_FOR_PASSWORD_SQL = "SELECT userid,username,pwdHash,pwhHashCode,birthday,sex,usertype,isfull,money FROM users where username=?";

    private static final String UPDATE_ADMIN_SQL="update users set %s where username='%s' ";

    //加密
    private StrongPasswordEncryptor strongPasswordEncryptor = new StrongPasswordEncryptor();
    private StrongTextEncryptor strongTextEncryptor = new StrongTextEncryptor();
    //解密


    @Override
    public Users create(Users user) throws Exception {
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement ps = conn.prepareStatement(ADD_USERS_SQL, Statement.RETURN_GENERATED_KEYS);) {
            System.out.println(user.getBirthday() + "---user.getBirthday");
            ps.setString(1, user.getUsername());
            ps.setString(2, user.getPwdHash());
            ps.setString(3, user.getPwhHashCode());
            ps.setDate(4, Objects.nonNull(user.getBirthday()) ? new Date(user.getBirthday().getTime()): null);
            ps.setString(5, user.getSex());
            ps.setLong(6,user.getUsertype());
            ps.setString(7,user.getIsfull());
            ps.setDouble(8,user.getMoney());
            ps.executeUpdate();
            ResultSet rs = ps.getGeneratedKeys();//拿到生成的主键
            if (rs.next()) {
                user.setUserid(rs.getLong(1));
            }
            return user;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Users getByUsername(String username) throws Exception {
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement ps = conn.prepareStatement(GET_BY_USERNAME, Statement.RETURN_GENERATED_KEYS);) {
            ps.setString(1, username);
            ResultSet rs = ps.executeQuery();
            Users users = null;
            if (rs.next()) {
                users = getUserFromResultSet(rs);
            }
            return users;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Book addBook(Book book) throws Exception {
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement ps = conn.prepareStatement(ADD_BOOK_SQL, Statement.RETURN_GENERATED_KEYS)) {
            ps.setString(1, book.getBookname());//书名
            //bookname,author,publish,bookcount,booktype
            ps.setString(2, book.getAuthor());//作者
            ps.setString(3, book.getPublish());//出版社
            ps.setLong(4, book.getBookcount());//数量
            ps.setString(5, book.getBooktype());//类型
            ps.executeUpdate();
            ResultSet rs = ps.getGeneratedKeys();//拿到生成的主键
            if (rs.next()) {
                book.setBookid(rs.getLong(1));
            }
            return book;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }


    }

    //找到名字一样的图书就把添加的图书加上这次添加的图书库存加上，如果不存在这本书，就另外添加
    @Override
    public Book getByBookname(String bookname) throws Exception {
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement ps = conn.prepareStatement(GET_BY_BOOKNAME_SQL, Statement.RETURN_GENERATED_KEYS);) {
            ps.setString(1, bookname);
            ResultSet rs = ps.executeQuery();
            Book book = null;
            if (rs.next()) {
                book = getBookFromResource(rs);
            }
            return book;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Book updateByBook(Book book) throws Exception {
        List<String> segments = new ArrayList<>();
        List<String> params = new ArrayList<>();
        if(Objects.nonNull(book.getBookname())&&!book.getBookname().isEmpty()){
            segments.add("bookname=?");
            params.add(book.getBookname());
        }
        if(Objects.nonNull(book.getPublish())&&!book.getPublish().isEmpty()){
            segments.add("publish=?");
            params.add(book.getPublish());
        }
        if(Objects.nonNull(book.getAuthor())&&!book.getAuthor().isEmpty()){
            segments.add("author=?");
            params.add(book.getAuthor());
        }
        if(Objects.nonNull(book.getBookcount())){
            segments.add("bookcount=?");
            params.add(String.valueOf(book.getBookcount()));
        }
        if(Objects.nonNull(book.getBooktype())&&!book.getBooktype().isEmpty()) {
            segments.add("booktype=?");
            params.add(book.getBooktype());
        }
        if(segments.isEmpty()){
            return getBybookId(book.getBookid());
        }
        String sql = String.format("UPDATE book SET %s WHERE bookid='%d';", String.join(",", segments), book.getBookid());
        try(Connection conn=DBUtil.getConnection();
        PreparedStatement ps = conn.prepareStatement(sql);)
        {
            for(int i=0;i<params.size();i++){
                ps.setString(i+1, params.get(i));
            }
            ps.executeUpdate();
            return getBybookId(book.getBookid());
        }catch (Exception e){
            throw new RuntimeException(e);
        }

    }

    @Override
    public Book getBybookId(long bookid) throws Exception {
       try(Connection conn=DBUtil.getConnection();
       PreparedStatement ps=conn.prepareStatement(GET_BY_BOOKID_SQL);){
           ps.setLong(1,bookid);
           ResultSet rs=ps.executeQuery();
           Book book=null;
           if(rs.next()){
               book=getBookFromResource(rs);
           }
           return book;
       }catch (SQLException e){
           throw new RuntimeException(e);
       }
    }


    @Override
    public Users updatePassword(Users user) throws Exception {
        List<String> segments = new ArrayList<>();
        List<String> params = new ArrayList<>();
        String s = strongPasswordEncryptor.encryptPassword(user.getPwdHash());
        if (Objects.nonNull(user.getPwdHash()) && !user.getPwdHash().isEmpty()) {
            segments.add("pwdHash=?");
            params.add(s);
        }
        segments.add("pwhHashCode=?");
        strongTextEncryptor.setPassword(s);
        params.add(strongTextEncryptor.encrypt(user.getPwdHash()));
        if (segments.isEmpty()) {
            return getByUserid(user.getUserid());
        }
        String sql = String.format("UPDATE users SET %s WHERE userid=%d;", String.join(",", segments), user.getUserid());
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement ps = conn.prepareStatement(sql);) {

            for (int i = 0; i < params.size(); i++) {
                ps.setString(i + 1, params.get(i));

            }
            System.out.println("sql:"+sql);
            ps.executeUpdate();
            return getByUserid(user.getUserid());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
    //匹配名字和密码,拿到输入的密码加密，在和数据库里面的密码匹配，如果匹配成功，则让新密码取代原密码，否则不匹配

    @Override
    public Users getByUsernameForPassword(String username, String pwdHash) throws Exception {

        try (Connection conn = DBUtil.getConnection();
             PreparedStatement ps = conn.prepareStatement(GET_BY_USERNAME_FOR_PASSWORD_SQL, Statement.RETURN_GENERATED_KEYS)) {
            ps.setString(1, username);
            ResultSet rs = ps.executeQuery();

            Users user = null;
            if (rs.next()) {
                String storedPassword = rs.getString("pwdHash");
                boolean b = false;
                b=strongPasswordEncryptor.checkPassword(pwdHash,storedPassword);
                if (b) {
                    user = getUserFromResultSet(rs);
                }
            }
            return user;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    public Users getByUserid(long userid) throws Exception {
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement ps = conn.prepareStatement(GET_BY_USERID_SQL);) {
            ps.setLong(1, userid);
            ResultSet rs = ps.executeQuery();
            Users user = null;
            if (rs.next()) {
                user = getUserFromResultSet(rs);
            }
            return user;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Users updateAdmin(Users user) throws Exception {
        List<String> segments = new ArrayList<>();
        List<Object> params = new ArrayList<>();

        if (Objects.nonNull(user.getUsername()) && !user.getUsername().isEmpty()) {
            segments.add("username=?");
            params.add(user.getUsername());
        }
        if (Objects.nonNull(user.getSex()) && !user.getSex().isEmpty()) {
            segments.add("sex=?");
            params.add(user.getSex());
        }
        String s = strongPasswordEncryptor.encryptPassword(user.getPwdHash());
        if (Objects.nonNull(user.getPwdHash()) && !user.getPwdHash().isEmpty()) {
            segments.add("pwdHash=?");
            params.add(s);
            segments.add("pwhHashCode=?");
            strongTextEncryptor.setPassword(s);
            params.add(strongTextEncryptor.encrypt(user.getPwdHash()));
        }

        if (Objects.nonNull(user.getBirthday())) {
            segments.add("birthday=?");
            params.add(user.getBirthday());
        }
        if (user.getUsertype()>=1) {
            segments.add("usertype=?");
            params.add(user.getUsertype());
        }
        if (segments.isEmpty()) {
            return getByUserid(user.getUserid());
        }
        String sql = String.format(UPDATE_ADMIN_SQL, String.join(",", segments), user.getUsername());
        try (Connection conn = DBUtil.getConnection();
             PreparedStatement ps = conn.prepareStatement(sql)) {
            for (int i = 0; i < params.size(); i++) {
                Object param = params.get(i);
                if (param instanceof java.util.Date) {
                    java.util.Date date = (java.util.Date) param;
                    ps.setDate(i + 1, new Date(date.getTime()));
                } else if(param instanceof Long){
                    ps.setLong(i + 1, (Long) param);
                }else {
                    ps.setString(i + 1, (String) param);
                }
            }

            ps.executeUpdate();
            return getByUserid(user.getUserid());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    private  static  Book getBookFromResource(ResultSet rs)throws Exception {
         Book book=new Book();
         book.setBookid(rs.getLong("bookid"));
         book.setBookname(rs.getString("bookname"));
         book.setPublish(rs.getString("publish"));
         book.setAuthor(rs.getString("author"));
         book.setBookcount(rs.getLong("bookcount"));
         book.setBooktype(rs.getString("booktype"));
         return  book;
       }

    private static Users getUserFromResultSet(ResultSet rs) throws SQLException {
        Users user = new Users();
        user.setUserid(rs.getLong("userid"));
        user.setUsername(rs.getString("username"));
        user.setPwdHash(rs.getString("pwdHash"));
        user.setPwhHashCode(rs.getString("pwhHashCode"));
        user.setBirthday(rs.getDate("birthday"));
        user.setSex(rs.getString("sex"));
        user.setUsertype(rs.getLong("userType"));
        return user;
    }


}
